package com.qhit.dao;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * TODO
 *
 * @author 村头老杨头
 * @version 1.0
 * @date 2021/9/28 9:44
 */
public class BaseDao<T> {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    private Connection conn;
    private PreparedStatement ps;
    private ResultSet rs;

    static {
        //读取配置文件
        Properties properties = new Properties();
        try {
            InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
            properties.load(is);
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //加载驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //创建连接
    public Connection getConnection(){
        if(conn==null){
            //创建连接
            try {
                conn = DriverManager.getConnection(url, username, password);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return conn;
    }
    //查询方法
    public List<T> executeQuery(Class cla, String sql, Object ...objs) {
        List<T> list = new ArrayList<>();
        //获得连接
        Connection conn = getConnection();
        //SQL预处理
        try {
            ps = conn.prepareStatement(sql);
            //填充问号
            for (int i = 0; i < objs.length; i++) {
                ps.setObject(i+1,objs[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()){
                //创建对象
                T obj = (T) cla.newInstance();
//        1、ResultSetMetaData元数据类，获得表所有的字段名
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    //表中的字段名
                    String columnName = rsmd.getColumnName(i);
//              2、通过结果集rs.getObject(字段名)，获得字段对应的数据值
                    Object columnValue = rs.getObject(columnName);
//              3、获得真实类的字段的反射对象Field, Field field = clz.getDeclaredField(字段名)
                    Field field = cla.getDeclaredField(columnName);
//              4、通过字段反射对象Field.set(真实对象,数据值)，设置属性值。
                    field.setAccessible(true);
                    field.set(obj,columnValue);
                }
                //添加对象到集合中
                list.add(obj);
            }
            close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return list;
    }
    //增删改  sql, 张三,23   objs[]{张三,23}
    public int executeUpdate(String sql, Object ...objs){
        int num = -1;
        Connection conn = getConnection();
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < objs.length; i++) {
                ps.setObject(i+1,objs[i]);
            }
            num = ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        close();
        return num;
    }
    //关闭资源
    private void close(){
        try{
            if (rs!=null){
                rs.close();
            }
            if(ps!=null){
                ps.close();
            }
            if (conn != null){
                conn.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
